package ch.myDungeons.game;

import java.util.ArrayList;

import ch.myDungeons.io.LanguagePack;
import ch.myDungeons.game.MyDungeon;
import ch.myDungeons.view.MapView;

/**
 * Displays the current map and grants static access to its main functions
 * @author Grii
 *
 */

public class MapDisplay {
	
	/** The map to display */
	public Map map;
	
	public MapView mapView;
	
	public MapDisplay(Map map, MapView mapView) {
		this.map = map;
		this.mapView = mapView;
	}
	
	/** Prints the map as a string to the console */
	public void printMap(){
		String mapOutput = "";
		for (int i = -2; i < map.tiles.length; i++) {
			mapOutput += "#";
		}
		mapOutput += "\n";
		ArrayList<Integer> health = new ArrayList();
		for (int y = 0; y < map.tiles[0].length; y++) {
			mapOutput += "#";
			for (int x = 0; x < map.tiles.length; x++) {
				if(checkOccupied(x, y)){
					if (map.tiles[x][y].personOnTheTile == MyDungeon.game.player) {
						int hp = (int)(255.0 * map.tiles[x][y].personOnTheTile.getCurrentHP() / map.tiles[x][y].personOnTheTile.getMaxHP());
						mapOutput += "P";
						health.add(hp);
					} else if (checkForAlly(x, y)) {
						int hp = (int)((255.0 * map.tiles[x][y].personOnTheTile.getCurrentHP()) / map.tiles[x][y].personOnTheTile.getMaxHP());
						mapOutput += "A";
						health.add(hp);
					} else {
						int hp = (int)((255.0 * map.tiles[x][y].personOnTheTile.getCurrentHP()) / map.tiles[x][y].personOnTheTile.getMaxHP());
						mapOutput += "E";
						health.add(hp);
					}
				} else if(checkObstacle(x, y)){
					mapOutput += "#";
				} else if(map.tiles[x][y].inventory.size() != 0){
					mapOutput += ",";
				} else if(map.tiles[x][y].isStairsDown){
					mapOutput += ">";
				} else if(map.tiles[x][y].isStairsUp){
					mapOutput += "<";
				} else {
					mapOutput += ".";
				}
			}
			mapOutput += "#\n";
		}
		for (int i = -2; i < map.tiles.length; i++) {
			mapOutput += "#";
		}
		mapView.updateMap(mapOutput, health);
	}
	
	/** Check if the target tile is an obstacle */
	public boolean checkObstacle(int posX, int posY) {
		return map.checkObstacle(posX, posY);
	}
	
	/** Check if the target tile is occupied by a character */
	public boolean checkOccupied(int posX, int posY) {
		return map.checkOccupied(posX, posY);
	}

	/** Check if the target tile is occupied by an enemy */
	public boolean checkForEnemy(int posX, int posY) {
		return map.checkForEnemy(posX, posY);
	}
	
	/** Check if the target tile is occupied by an ally */
	public boolean checkForAlly(int posX, int posY) {
		return map.checkForAlly(posX, posY);
	}

	/** Check if the target tile is free to access */
	public boolean checkAccessability(int posX, int posY) {
		return map.checkAccessability(posX, posY);
	}
	
	/** Returns a string containing the stats of the tile */
	public String getInfo(int xPos, int yPos){
		String result = LanguagePack.get("tile") + " (" + xPos + "/" + yPos + ")\n";
		Tile tile = map.tiles[xPos][yPos];
		if (tile.isStairsUp) {
			result = LanguagePack.get("tile") + " (" + xPos + "/" + yPos + ")\n" + LanguagePack.get("stairs_up") + "n";
		}
		if (tile.isStairsDown) {
			result = LanguagePack.get("tile") + " (" + xPos + "/" + yPos + ")\n" + LanguagePack.get("stairs_down") + "\n";
		}
		
		if (tile.personOnTheTile != null) {
			result += tile.personOnTheTile.getInfo();
		} else {
			if (tile.accessible) {
				if (tile.inventory.isEmpty()) {
					result += LanguagePack.get("empty_floor");
				} else {
					if (tile.inventory.size() == 1) {
						result += LanguagePack.get("there_is") + " " + tile.inventory.size() + " " + LanguagePack.get("item_on_this_tile") + ":";
					} else {
						result += LanguagePack.get("there_are") + " " + tile.inventory.size() + " " + LanguagePack.get("items_on_this_tile") + ":";
					}
					for (int i = 0; i < tile.inventory.size(); i++) {
						result += "\n " + i + ": " + tile.inventory.get(i).getNameWithCount();
					}
				}
			} else {
				result += LanguagePack.get("obstacle");
			}
		}
		return result;
	}
	

	public void changeMap(Map map) {
		this.map = map;
		printMap();
	}
}
